/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once

#include "stdafx.h"
#include "commontypes.h"
#include "image_acquisition_model.h"
#include "image_site.h"
#include "event_callback.h"
#include "list.h"


class WiaModel : public ImageAcquisitionModel
{
public:

	WiaModel( ImageSite* imageSite, MessageListener* messageListener );
	virtual ~WiaModel();

	// ImageAcquisitionModel interface implementation
	virtual int getModelTypeId() const { return 2; }
	virtual char* getModelTypeName() const { return ( char* ) m_modelTypeName; }
	virtual void setIdentity( char* productName );
	virtual bool getDevices();
	virtual ImagingDevice* getDevice( int index );
	virtual int getDeviceCount();

	virtual ResultCode scan();

	virtual PixelType getPixelType() const { return m_pixelType; }
	virtual void setPixelType( PixelType value );
	virtual uint_t getResolution() const { return m_resolution; }
	virtual void setResolution( uint_t value ) { m_resolution = value; }
	virtual PaperSource getPaperSource() const { return m_paperSource; }
	virtual void setPaperSource( PaperSource value );
	virtual bool getAutoBright() const { return m_autoBright; }
	virtual void setAutoBright( bool value ) { m_autoBright = value; }
	virtual int getContrast() const { return m_contrast; }
	virtual void setContrast( int value ) { m_contrast = value; }
	virtual double getPageWidth() const { return m_pageWidth; }
	virtual void setPageWidth( double value ) { if ( value > 0 ) m_pageWidth = value; }
	virtual double getPageHeight() const { return m_pageHeight; }
	virtual void setPageHeight( double value ) { if ( value > 0 ) m_pageHeight = value; }
	virtual void setPageSize( double width, double height ) { if ( width > 0 && height > 0 ) { m_pageWidth = width; m_pageHeight = height; } }

	virtual bool getIsPaperSourceFixed() const { return m_isPaperSourceFixed; }

	virtual bool getDuplex() const { return m_duplex; }
	virtual void setDuplex( bool value ) { m_duplex = m_isFeederSupported && value; }

	virtual int getOrientation() const { return m_orientation; }
	virtual void setOrientation( int value ) { m_orientation = value; }

	virtual bool getIsDeviceFeatureSupported( DeviceFeature deviceFeature ) const;
	virtual long initializeDevice();

	virtual bool getShowDeviceUI() const { return m_showDeviceUI; }
	virtual void setShowDeviceUI( bool value ) { m_showDeviceUI = value; }

	virtual void setParentWindow( void* handle ) { }

	virtual int getDeviceIndex() const { return m_deviceIndex; }
	virtual void setDeviceIndex( int value );

	virtual const ImagingDevice& getCurrentDevice() const { return m_devices[ m_deviceIndex ]; }

	virtual BaseCap* getCap( uint_t cap );

	virtual bool connect();
	virtual void disconnect();
	virtual bool getIsConnected() const { return m_connected; }

	virtual void deviceChange( bool state ) { }

private:

	HRESULT getImage( IWiaDevMgr* pWiaDevMgr, bool showDeviceUI, LONG *plCount, IStream ***pppStream );
	long getImages();

private:

	static uint_t m_osMajorVersion;

	MessageListener* m_messageListener;
	CComPtr<IWiaDevMgr> m_pWiaDevMgr; // WIA 1.0 device manager (Windows XP)
	CComPtr<IWiaDevMgr2> m_pWiaDevMgr2; // WIA 2.0 device manager (Windows Vista and higher)
	CComPtr<IUnknown> m_pConnectEventObject;
	CComPtr<IUnknown> m_pDisconnectEventObject;
	CEventCallback* m_pEventCallback;
	IWiaItem* m_pItemDevice, *m_pItemRoot;
	IWiaItem2* m_pItemDevice2, *m_pItemRoot2;
	IWiaItem* m_pItemSubDevice2;
	int m_deviceIndex;
	bool m_devMgrInitialized, m_devInitialized;

	List<ImagingDevice> m_devices;

	uint_t m_resolution;
	PixelType m_pixelType;
	long m_colorDepth;
	long m_dataType;
	long m_imageTypeIntent;
	PaperSource m_paperSource;
	bool m_autoBright;
	int m_contrast;
	double m_pageWidth, m_pageHeight;
	int m_orientation;
	bool m_duplex;

	bool m_isFlatbedSupported, m_isFeederSupported, m_isDuplexSupported, m_isPaperSourceFixed;
	int m_maxHorizontalSize, m_minHorizontalSize, m_maxVerticalSize, m_minVerticalSize;
	int m_opticalXres, m_opticalYres;

	bool m_showDeviceUI;

	static char m_modelTypeName[];

	ImageSite* m_pImageSite;

	bool m_connected;
};
